#ifndef _VL_DISPATCHER__H_
#define _VL_DISPATCHER__H_

#include <deque>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <thread>
#include <string>

namespace VL {

using dispatch_run_cb = std::function<void()>;

/**
 * @Author: CimZzz
 * @Date: 2023-09-04 17:22:53
 * 
 * 分发消息基类
 */
struct dispatch_base_msg {
	virtual ~dispatch_base_msg();
	// 执行消息回调
	virtual void invoke() = 0;
	// 取消消息回调
	virtual void cancel() = 0;
};

/**
 * @Author: CimZzz
 * @Date: 2023-09-04 17:26:22
 * 
 * 基础分发消息
 */
struct dispatch_runnable_msg: public dispatch_base_msg {
public:
	dispatch_runnable_msg(dispatch_run_cb cb);
	virtual void invoke() override;
	virtual void cancel() override;
private:
	dispatch_run_cb _cb = nullptr;
};


/**
 * @Author: CimZzz
 * @Date: 2023-08-30 18:16:18
 * 
 * 分发器状态
 */
enum class dispatcher_status {
	// 初始化状态
	Init,
	// 启动中状态
	Starting,
	// 已启动状态
	Started,
	// 安全退出中状态
	SafeQuiting,
	// 退出中状态
	Quiting,
	// 已退出状态
	Quit,
};

/**
 * @Author: CimZzz
 * @Date: 2023-08-30 17:51:58
 * 
 * 分发器
 */
class dispatcher {
public:
	explicit dispatcher(const std::string& name = "");
	virtual ~dispatcher();

	virtual void start();
	virtual void start_sync();
	
	bool is_async();

	void dispatch_run(const dispatch_run_cb& cb, bool runWhenSameThread = true);
	void dispatch_first_run(const dispatch_run_cb& cb, bool runWhenSameThread = true);

	virtual void quit();
	virtual void quit_sync();
	virtual void quit_safety();
	virtual void quit_safety_sync();

protected:
	void dispatch_msg(dispatch_base_msg* msg, bool runWhenSameThread = true);
	void dispatch_msg_at_first(dispatch_base_msg* msg, bool runWhenSameThread = true);
	void loop();

protected:
	// 分发器状态
	volatile dispatcher_status status;
	// 分发器名称
	std::string name;
	// 分发回调队列
	std::deque<dispatch_base_msg*> queue;
	// 线程锁
	std::mutex mutex;
	// 条件变量
	std::condition_variable cond;
	// 所在线程 Id
	std::thread::id tid;
};

/**
 * @Author: CimZzz
 * @Date: 2023-08-30 18:50:52
 * 
 * 异步分发器
 */
class async_dispatcher: public dispatcher {
public:
	explicit async_dispatcher(const std::string& name = "");
	virtual ~async_dispatcher();

	virtual void start();
	virtual void start_sync();

	virtual void quit();
	virtual void quit_sync();
	virtual void quit_safety();
	virtual void quit_safety_sync();
private:
	// 线程指针
	std::thread* threadPtr;
	// 关闭条件变量
	std::condition_variable statusCond;
};

}

#endif // end _VL_DISPATCHER__H_